package com.example.demo.controller;

import com.aliyun.opensearch.sdk.generated.commons.OpenSearchClientException;
import com.aliyun.opensearch.sdk.generated.commons.OpenSearchException;
import com.example.demo.constant.Code;
import com.example.demo.enumeration.Campus;
import com.example.demo.enumeration.ItemCategory;
import com.example.demo.enumeration.ItemStatus;
import com.example.demo.enumeration.SortOrder;
import com.example.demo.pojo.Result;
import com.example.demo.pojo.dto.*;
import com.example.demo.pojo.entity.Item;
import com.example.demo.pojo.entity.Report;
import com.example.demo.pojo.properties.AliyunOpenSearchProperties;
import com.example.demo.pojo.vo.*;
import com.example.demo.service.ItemService;
import com.example.demo.service.UserService;
import com.example.demo.utils.AliyunOpenSearchUtil;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.List;

@RestController
@RequestMapping("/item")
@Validated
public class ItemController {
    @Autowired
    private ItemService itemService;
    @Autowired
    private UserService userService;

    /* 阿里云OpenSearch续费太贵，暂时停用
    @Autowired
    private AliyunOpenSearchProperties aliyunOpenSearchProperties;
    */

    private Result checkUpdate(Long itemId) {
        Long userId = itemService.selectUserIdByItemId(itemId);
        if (userId == null) {
            return new Result(Code.UPDATE_ERR, null, "目标商品不存在");
        }

        Long currentUserId = userService.getCurrentUserId();
        if (!userId.equals(currentUserId)) {
            return new Result(Code.UPDATE_ERR, null, "不能更新不属于自己的商品");
        }

        ItemStatus itemStatus = itemService.selectStatusByItemId(itemId);
        if (itemStatus.equals(ItemStatus.sold) || itemStatus.equals(ItemStatus.trading)) {
            return new Result(Code.UPDATE_ERR, null, "不能更改交易进行中或交易结束的商品");
        }

        return null;
    }

    @PostMapping("/add")
    public Result addItem(@RequestBody @Valid AddItemDTO addItemDTO) {
        boolean result = itemService.addItem(addItemDTO);

        int code = (result) ? Code.INSERT_OK : Code.INSERT_ERR;
        String message = (result) ? "新增商品成功" : "新增商品失败，请重试";

        return new Result(code, null, message);
    }

    @GetMapping("/{itemId}")
    public Result getDetail(@PathVariable Long itemId) {
        ItemDetailVO itemDetailVO = itemService.getDetail(itemId);

        if (itemDetailVO == null) {
            return new Result(Code.SELECT_ERR, null, "目标商品不存在");
        }

        ItemStatus status = itemDetailVO.getStatus();

        if (status.equals(ItemStatus.pending) || status.equals(ItemStatus.rejected)) {
            Long userId = itemDetailVO.getUserId();
            Long currentUserId = userService.getCurrentUserId();

            if (!userId.equals(currentUserId)) {
                return new Result(Code.SELECT_ERR, null, "该商品未通过审核，无法查看");
            }
        }

        return new Result(Code.SELECT_OK, itemDetailVO, "获取商品详情成功");
    }

    @PutMapping("/update")
    public Result updateItem(@RequestBody @Valid UpdateItemDTO updateItemDTO) {
        Long itemId = updateItemDTO.getId();

        Result checkResult = checkUpdate(itemId);
        if (checkResult != null) {
            return checkResult;
        }

        boolean result = itemService.updateItem(updateItemDTO);

        int code = (result) ? Code.UPDATE_OK : Code.UPDATE_ERR;
        String message = (result) ? "更新商品信息成功" : "更新商品信息失败，请重试";

        return new Result(code, null, message);
    }

    @PatchMapping("/update_price")
    public Result updatePrice(@RequestBody @Validated(ValidateGroup.Crud.Update.class) Item item) {
        Long itemId = item.getId();

        Result checkResult = checkUpdate(itemId);
        if (checkResult != null) {
            return checkResult;
        }

        boolean result = itemService.updatePrice(itemId, item.getPrice());

        int code = (result) ? Code.UPDATE_OK : Code.UPDATE_ERR;
        String message = (result) ? "更新商品价格成功" : "更新商品价格失败，请重试";

        return new Result(code, null, message);
    }

    @PatchMapping("/update_images")
    public Result updateImages(@RequestBody @Valid UpdateItemImagesDTO updateItemImagesDTO) {
        Long itemId = updateItemImagesDTO.getId();

        Result checkResult = checkUpdate(itemId);
        if (checkResult != null) {
            return checkResult;
        }

        boolean result = itemService.updateImages(itemId, updateItemImagesDTO.getImages());

        int code = (result) ? Code.UPDATE_OK : Code.UPDATE_ERR;
        String message = (result) ? "更新商品图片成功" : "更新商品图片失败，请重试";

        return new Result(code, null, message);
    }

    @DeleteMapping("/{itemId}")
    public Result deleteItem(@PathVariable Long itemId) {
        Long userId = itemService.selectUserIdByItemId(itemId);

        if (userId == null) {
            return new Result(Code.DELETE_ERR, null, "目标商品不存在");
        }

        Long currentUserId = userService.getCurrentUserId();

        if (!userId.equals(currentUserId)) {
            return new Result(Code.DELETE_ERR, null, "不能删除不属于自己的商品");
        }

        ItemStatus itemStatus = itemService.selectStatusByItemId(itemId);
        if (itemStatus.equals(ItemStatus.sold) || itemStatus.equals(ItemStatus.trading)) {
            return new Result(Code.DELETE_ERR, null, "不能删除交易进行中或交易结束的商品");
        }

        boolean result = itemService.deleteItem(itemId);

        int code = (result) ? Code.DELETE_OK : Code.DELETE_ERR;
        String message = (result) ? "删除商品成功" : "删除商品失败，请重试";

        return new Result(code, null, message);
    }

    @GetMapping("/list")
    public Result getCurrentItemList() {
        List<ItemListVO> currentItemList = itemService.getCurrentItemList();

        return new Result(Code.SELECT_OK, currentItemList, "查询当前用户商品列表成功");
    }

    @GetMapping("/list/{userId}")
    public Result getItemListByUserId(@PathVariable Long userId) {
        List<ItemListVO> itemListByUserId = itemService.getItemListByUserId(userId);

        return new Result(Code.SELECT_OK, itemListByUserId, "查询商品列表成功");
    }

    @GetMapping("/search")
    public Result searchItemList(@RequestParam(defaultValue = "1") int page,
                                 @RequestParam(required = false) String keyword,
                                 @RequestParam(required = false) ItemCategory category,
                                 @RequestParam(required = false) Campus campus,
                                 @RequestParam(required = false, name = "min_price") BigDecimal minPrice,
                                 @RequestParam(required = false, name = "max_price") BigDecimal maxPrice,
                                 @RequestParam(required = false, name = "sort_by_price") SortOrder sortByPrice
                                 ) {
        /* 通过阿里云OpenSearch搜索数据，OpenSearch续费太贵，暂时停用，替换为模糊查询
        try {
            OpenSearchSelectItemDTO openSearchSelectItemDTO = AliyunOpenSearchUtil.searchItem(aliyunOpenSearchProperties, page, keyword, category, campus, minPrice, maxPrice, sortByPrice);
            String errors = openSearchSelectItemDTO.getErrors();

            if (errors != null) {
                System.out.println(errors);
            }

            PageVO pageVO = new PageVO();
            pageVO.setTotal(openSearchSelectItemDTO.getTotal());

            List itemListByIdList = itemService.getItemListByIdList(openSearchSelectItemDTO.getList());

            pageVO.setList(itemListByIdList);

            return new Result(Code.SELECT_OK, pageVO, "查询商品列表成功");

        } catch (OpenSearchClientException | OpenSearchException e) {
            e.printStackTrace();
            return new Result(Code.OPEN_SEARCH_ERR, null, e.getMessage());
        }
        */
        PageVO pageVO = itemService.searchItem(page, keyword, category, campus, minPrice, maxPrice, sortByPrice);

        return new Result(Code.SELECT_OK, pageVO, "查询成功");
    }

    @PostMapping("/comment/add")
    public Result addComment(@RequestBody @Valid AddCommentDTO addCommentDTO) {
        Long itemId = addCommentDTO.getItemId();
        ItemStatus status = itemService.selectStatusByItemId(itemId);

        if (status == null) {
            return new Result(Code.INSERT_ERR, null, "该商品不存在");
        }

        if (status.equals(ItemStatus.pending) || status.equals(ItemStatus.rejected)) {
            return new Result(Code.INSERT_ERR, null, "目标商品未过审，不能添加评论");
        }

        Long parentId = addCommentDTO.getParentId();
        if (parentId != null) {
            Long parent = itemService.selectParentIdByCommentId(parentId);
            if (parent != null) {
                return new Result(Code.INSERT_ERR, null, "新增评论的父评论不是父评论");
            }

            Long itemIdOfParentComment = itemService.selectItemIdByCommentId(parentId);
            if (itemIdOfParentComment == null) {
                return new Result(Code.INSERT_ERR, null, "新增评论的父评论不存在");
            }

            if (!itemIdOfParentComment.equals(itemId)) {
                return new Result(Code.INSERT_ERR, null, "新增评论的商品与父评论商品不一致");
            }
        }

        Long replyId = addCommentDTO.getReplyId();
        if (replyId != null) {
            Long parentIdOfReplyComment = itemService.selectParentIdByCommentId(replyId);
            if (parentIdOfReplyComment == null) {
                return new Result(Code.INSERT_ERR, null, "新增评论回复的子评论不存在");
            }

            if (!parentIdOfReplyComment.equals(parentId)) {
                return new Result(Code.INSERT_ERR, null, "新增评论的父评论与回复的子评论的父评论不一致");
            }
        }

        boolean result = itemService.addComment(addCommentDTO);

        int code = (result) ? Code.INSERT_OK : Code.INSERT_ERR;
        String message = (result) ? "新增评论成功" : "新增评论失败，请重试";

        return new Result(code, null, message);
    }

    @DeleteMapping("/comment/{commentId}")
    public Result deleteComment(@PathVariable Long commentId) {
        Long userId = itemService.selectUserIdByCommentId(commentId);

        if (userId == null) {
            return new Result(Code.DELETE_ERR, null, "目标评论不存在");
        }

        Long currentUserId = userService.getCurrentUserId();

        if (!userId.equals(currentUserId)) {
            return new Result(Code.DELETE_ERR, null, "不能删除不属于自己的评论");
        }

        boolean result = itemService.deleteComment(commentId);

        int code = (result) ? Code.DELETE_OK : Code.DELETE_ERR;
        String message = (result) ? "删除评论成功" : "删除评论失败，请重试";

        return new Result(code, null, message);
    }

    @GetMapping("/comment/list")
    public Result getItemCommentList(@RequestBody @Validated(ValidateGroup.Crud.Read.class) Item item) {
        Long itemId = item.getId();

        ItemStatus status = itemService.selectStatusByItemId(itemId);
        if (status == null) {
            return new Result(Code.SELECT_ERR, null, "该商品不存在");
        }

        if (status.equals(ItemStatus.pending) || status.equals(ItemStatus.rejected)) {
            return new Result(Code.SELECT_ERR, null, "不能查看未过审商品的评论");
        }

        List<CommentVO> itemCommentList = itemService.getItemCommentList(itemId);

        return new Result(Code.SELECT_OK, itemCommentList, "查询商品评论成功");
    }

    @GetMapping("/comment/user_list")
    public Result getCurrentCommentList() {
        List<UserCommentVO> currentCommentList = itemService.getCurrentCommentList();

        return new Result(Code.SELECT_OK, currentCommentList, "查询当前用户评论成功");
    }

    @PostMapping("/report")
    public Result reportItem(@RequestBody @Validated({ValidateGroup.ItemReport.class, ValidateGroup.Report.class}) Report report) {
        Long itemId = report.getItemId();
        ItemStatus itemStatus = itemService.selectStatusByItemId(itemId);
        if (itemStatus == null) {
            return new Result(Code.INSERT_ERR, null, "该商品不存在");
        }

        if (ItemStatus.pending.equals(itemStatus) || ItemStatus.rejected.equals(itemStatus)) {
            return new Result(Code.INSERT_ERR, null, "不能举报未通过审核的商品");
        }

        boolean result = itemService.reportItem(itemId, report.getReason(), report.getImage());

        int code = (result) ? Code.INSERT_OK : Code.INSERT_ERR;
        String message = (result) ? "举报商品成功" : "举报商品失败，请重试";

        return new Result(code, null, message);
    }

    @PostMapping("/comment/report")
    public Result reportItemComment(@RequestBody @Validated({ValidateGroup.CommentReport.class, ValidateGroup.Report.class}) Report report) {
        Long commentId = report.getCommentId();
        if (itemService.selectUserIdByCommentId(commentId) == null) {
            return new Result(Code.INSERT_ERR, null, "该评论不存在");
        }

        boolean result = itemService.reportItemComment(commentId, report.getReason(), report.getImage());

        int code = (result) ? Code.INSERT_OK : Code.INSERT_ERR;
        String message = (result) ? "举报商品评论成功" : "举报商品评论失败，请重试";

        return new Result(code, null, message);
    }
}
